package org.swingDemo.UI;

import cn.hutool.core.util.NumberUtil;
import com.esotericsoftware.tablelayout.swing.Table;
import com.formdev.flatlaf.FlatIntelliJLaf;
import org.swingDemo.helper.ClassifyOptionHelper;
import org.swingDemo.helper.StringHelper;
import org.swingDemo.swingWorker.FileClassifyWorker;

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class MainFrame extends JFrame implements PropertyChangeListener, WindowListener {

    public static MainFrame mainFrame;

    private FoldChooserPanel sourcePanel;
    private FoldChooserPanel targetPanel;
    private ClassifyOptionPanel classifyOptionPanel;
    private JTextPane outputPane;
    private CommandPanel commandPanel;

    private FileClassifyWorker fileClassifyWorker;

    public MainFrame() {
        super("文件自动分类");
        mainFrame = this;

        try {
            UIManager.setLookAndFeel(new FlatIntelliJLaf());

            initFrame();
            this.addWindowListener(this);
            this.setIconImage(new ImageIcon(MainFrame.class.getResource("/static/frame.png")).getImage());
            this.setMinimumSize(new Dimension(800, 600));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public boolean startFileClassifyWorker() {
        String sourcePath = sourcePanel.getFilePath();
        if (sourcePath.isEmpty()) {
            JOptionPane.showMessageDialog(this,
                    "请选择源目录");
            return false;
        }

        String targetPath = targetPanel.getFilePath();
        if (targetPath.isEmpty()) {
            JOptionPane.showMessageDialog(this,
                    "请选择目的目录");
            return false;
        }

        clearOutputPanel();
        ClassifyOptionHelper.setSourcePath(sourcePath);
        fileClassifyWorker = new FileClassifyWorker(sourcePath, targetPath);
        fileClassifyWorker.execute();
        return true;
    }

    public void stopFileClassifyWorker() {
        if (fileClassifyWorker != null && !fileClassifyWorker.isDone()) {
            fileClassifyWorker.cancel(false);
            while (!fileClassifyWorker.isDone()) {
                try {
                    Thread.sleep(100);
                } catch (Exception ex) {}
            }
        }

        fileClassifyWorker = null;
    }

    public void onFileClassifyWorkerDone() {
        commandPanel.handleFileClassifyWorkerDone();
        appendInfoMessage2OutputArea("分类操作完成");
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();
        if (propertyName.equals(StringHelper.PROPERTY_FILE_COUNT)) {
            commandPanel.setFileCount(NumberUtil.parseInt(evt.getNewValue().toString()));
        } if (propertyName.equals(StringHelper.PROPERTY_FILE_INDEX)) {
            commandPanel.setFileIndex(NumberUtil.parseInt(evt.getNewValue().toString()));
        } else if (propertyName.equals(StringHelper.PROPERTY_INFO)) {
            appendInfoMessage2OutputArea(evt.getNewValue().toString());
        } else if (propertyName.equals(StringHelper.PROPERTY_ERROR)) {
            appendErrorMessage2OutputArea(evt.getNewValue().toString());
        }
    }

    @Override
    public void windowOpened(WindowEvent e) {

    }

    @Override
    public void windowClosing(WindowEvent e) {
        if (fileClassifyWorker != null && !fileClassifyWorker.isDone()) {
            JOptionPane.showMessageDialog(this,
                    "正在进行文件分类,请停止分类后再关闭!");
            return;
        }
        this.setVisible(false);
        this.dispose();
    }

    @Override
    public void windowClosed(WindowEvent e) {

    }

    @Override
    public void windowIconified(WindowEvent e) {

    }

    @Override
    public void windowDeiconified(WindowEvent e) {

    }

    @Override
    public void windowActivated(WindowEvent e) {

    }

    @Override
    public void windowDeactivated(WindowEvent e) {

    }

    private void initFrame() {
        sourcePanel = new FoldChooserPanel(StringHelper.SOURCE_FOLDER);
        targetPanel = new FoldChooserPanel(StringHelper.TARGET_FOLDER);
        classifyOptionPanel = new ClassifyOptionPanel();
        outputPane = new JTextPane();
        outputPane.setEditable(false);
        commandPanel = new CommandPanel();

        Table mainTable = new Table();
        mainTable.addCell(sourcePanel).expandX().fillX().row();
        mainTable.addCell(targetPanel).expandX().fillX().row();
        mainTable.addCell(classifyOptionPanel).expandX().fillX().row();
        mainTable.addCell(new JScrollPane(outputPane)).expand().fill().row();
        mainTable.addCell(commandPanel).expandX().fillX();

        this.setLayout(new BorderLayout());
        this.add(mainTable);
    }

    private void appendInfoMessage2OutputArea(String message) {
        MutableAttributeSet attributeSet = new SimpleAttributeSet();
        StyleConstants.setItalic(attributeSet, true);
        StyleConstants.setForeground(attributeSet, Color.blue);
        appendMessage2OutputArea(message, attributeSet);
    }

    private void appendErrorMessage2OutputArea(String message) {
        MutableAttributeSet attributeSet = new SimpleAttributeSet();
        StyleConstants.setForeground(attributeSet, Color.red);
        appendMessage2OutputArea(message, attributeSet);
    }

    private void appendMessage2OutputArea(String message, AttributeSet attributeSet) {
        try {
            Position position = outputPane.getStyledDocument().getEndPosition();
            outputPane.getStyledDocument().insertString(position.getOffset(), message, attributeSet);
            position = outputPane.getStyledDocument().getEndPosition();
            outputPane.getStyledDocument().insertString(position.getOffset(), "\n", attributeSet);

            outputPane.setCaretPosition(outputPane.getStyledDocument().getLength());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void clearOutputPanel() {
        try {
            int length = outputPane.getDocument().getLength();
            outputPane.getDocument().remove(0, length);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
